
#ifndef __MODBUS_PROT_H__
#define __MODBUS_PROT_H__

#include <stdbool.h>
#include <stdlib.h>
#include <pthread.h>
#include <termios.h>
#include "modbus.h"
#include "modbus-rtu.h"
#include "modbus-tcp.h"
#include "modbus-version.h"

#define MODBUS_TABLE_SIZE(table) (sizeof(table) / sizeof(table[0]))    ///< 获取表大小
#define MODBUS_LOCK(lock)        pthread_mutex_lock(lock)              ///< 上锁
#define MODBUS_UNLOCK(lock)      pthread_mutex_unlock(lock)            ///< 解锁
#define MODBUS_RESEND_CNT        1                                     ///< 重发次数

/**
 * @brief Modbus 错误码枚举
 */
typedef enum
{
    e_ModbusErrNone = 0,           ///< 无错误
    e_ModbusRtuErrPtrNull = -2,    ///< modbus rtu指针为空
    e_ModbusTcpErrPtrNull = -3,    ///< modbus tcp指针为空
} E_ModbusErrCode;

/**
 * @brief MODBUS RTU配置结构体
 */
typedef struct
{
    const char *DevName;        ///< 设备名
    int         BaudRate;       ///< 波特率
    char        Parity;         ///< 校验位，无='N', 奇='O', 偶='E'
    int         DataBit;        ///< 数据位
    int         StopBit;        ///< 停止位
    int         DevId;          ///< 设备ID
    bool        IsDebug;        ///< 是否打印调试信息
    int         TimeoutSec;     ///< 超时时间，单位s
    int         TimeoutUSec;    ///< 超时时间，单位us
} TModbusRtuCfg;

/**
 * @brief MODBUS TCP配置结构体
 */
typedef struct
{
    char IpAddr[64];     ///< 设备名
    int  Port;           ///< 端口
    int  DevId;          ///< 设备ID
    bool IsDebug;        ///< 是否打印调试信息
    int  DataSize;       ///< 映射数据大小
    int  TimeoutSec;     ///< 超时时间，单位s
    int  TimeoutUSec;    ///< 超时时间，单位us
} TModbusTcpCfg;

/**
 * @brief Modbus 点表结构体
 */
typedef struct
{
    int StartAddr;       ///< 地址
    int RegNumber;       ///< 寄存器数量
    int FunctionCode;    ///< 功能码
} TModbusTable;

struct TModbusStu;
/**
 * @brief Modbus connect 回调函数
 * @param modbus_t modbus_t指针
 */
typedef int (*PFModbusConnectCb)(modbus_t *);
/**
 * @brief Modbus close 回调函数
 * @param modbus_t modbus_t指针
 */
typedef void (*PFModbusCloseCb)(modbus_t *);
/**
 * @brief Modbus reconnect 回调函数
 * @param TModbus Modbus 使用参数结构体指针
 */
typedef void (*PFModbusReconnectCb)(struct TModbusStu *);
/**
 * @brief Modbus read 回调函数
 * @param TModbus Modbus 使用参数结构体指针
 * @param TModbusTable Modbus 表结构体指针
 * @param int 表大小
 * @param int 读取寄存器起始地址
 * @param void 用户自定义参数指针
 */
typedef int (*PFModbusReadCb)(struct TModbusStu *, TModbusTable *, int, int, void *);
/**
 * @brief Modbus write 回调函数
 * @param TModbus Modbus 使用参数结构体指针
 * @param TModbusTable Modbus 表结构体指针
 * @param int 表大小
 * @param int 写入寄存器起始地址
 * @param void 用户自定义参数指针
 */
typedef int (*PFModbusWriteCb)(struct TModbusStu *, TModbusTable *, int, int, void *);

/**
 * @brief Modbus 使用参数结构体
 */
typedef struct TModbusStu
{
    /**
     * @brief 公共参数
     */
    modbus_t       *Modbus;    ///< modbus句柄
    pthread_mutex_t Lock;      ///< 互斥锁

    /**
     * @brief Rtu/Tcp 主站参数
     */
    PFModbusConnectCb   OnConnect;         ///< 连接回调函数
    PFModbusCloseCb     Onclose;           ///< 断开连接回调函数
    PFModbusReconnectCb OnReconnect;       ///< 重连回调函数
    PFModbusReadCb      OnRead;            ///< 读取回调函数
    PFModbusWriteCb     OnWrite;           ///< 写入回调函数
    bool                IsConnect;         ///< 是否连接
    bool                IsComm;            ///< 是否通信
    pthread_t           MasterThreadId;    ///< 主站线程

    /**
     * @brief Tcp 从站参数
     */
    int               Socket;           ///< 服务器套接字
    uint16_t          HearBeat;         ///< 心跳包
    modbus_mapping_t *Map;              ///< modbus映射表
    uint16_t         *Data;             ///< 数据映射区（主站读写的数据存放区）
    pthread_t         SlaveThreadId;    ///< 从站线程
} TModbus;

TModbus *modbus_rtu_master_create(TModbusRtuCfg tModbusRtuCfg);

TModbus *modbus_tcp_slave_create(TModbusTcpCfg tModbusTcpCfg, int iPriority);
TModbus *modbus_tcp_master_create(TModbusTcpCfg tModbusTcpCfg);

void modbus_rtu_master_demo(void);
void modbus_tcp_master_demo(void);
#endif
